import jwt
import hashlib
from jwt.exceptions import ExpiredSignatureError
from datetime import timedelta, datetime

# 过期间隔时间
EXPIRED_HOUR = 12

class UserToken(object):
    key = "lxqToken"
    salt = "lxq"

    # 把用户信息压缩成一串字符串，并附带12小时的过期时间。
    @staticmethod
    def get_token(data):
        # exp :  jwt的过期时间，这个过期时间必须要大于签发时间
        # datetime.utcnow()  世界标准时间
        # timedelta(hours=EXPIRED_HOUR)   ==> datetime.timedelta对象代表两个时间之间的时间差
        '''
        jwt.encode()参数:
        payload: Dict[str, Any],
        key: str,
        algorithm: Optional[str] = "HS256",
        headers: Optional[Dict] = None,
        json_encoder: Optional[Type[json.JSONEncoder]] = None,
        :param data:
        :return:
        '''
        new_data = dict({"exp": datetime.utcnow() + timedelta(hours=EXPIRED_HOUR), **data})
        return jwt.encode(new_data, key=UserToken.key)

    # 解析token为之前的用户信息
    @staticmethod
    def parse_token(token):
        try:
            return jwt.decode(token, key=UserToken.key,algorithms='HS256')
        except ExpiredSignatureError:
            raise Exception("token过期了，请重新登录")


    # 用md5码去存储用户密码
    @staticmethod
    def add_salt(password):
        '''
        add_salt是为了能够用md5码去存储用户密码，一旦有邪恶势力拿到数据库密码的话，不至于会暴露用户的密码，add_salt就是加盐的意思
        :param password:
        :return:
        update(arg)传入arg对象来更新hash的对象。必须注意的是，该方法只接受byte类型，否则会报错。这就是要在参数前添加b来转换类型的原因。
        '''
        m = hashlib.md5()
        # unicode必须hash成bytes
        bt = f"{password}{UserToken.salt}".encode("utf-8")
        # update(arg)传入arg对象来更新hash的对象。
        m.update(bt)
        # hexdigest()在英语中hex有十六进制的意思，因此该方法是将hash中的数据转换成数据，其中只包含十六进制的数字。
        return m.hexdigest()
